/***************************

VP

Function description:
  mex version of VP 
  vector post processing
  support 
  1. 
  2. 
  3. 

  parameter : 
              param(STRUCT)
  return    : vector_out (INT16 vector)

Version number: 1.0

Editor: source insight 3.1

Data : 2010-06-10

Author: Wang Dong

****************************/
/*--------------------------------------------------------------------
Data : 2010-06-10
Revise: add initiation coef to improve the smoothness of motion field
----------------------------------------------------------------------*/
#include <string.h>
#include <math.h>
#include "mex.h"

typedef unsigned char     UINT8;
typedef char              INT8;
typedef unsigned short    UINT16;
typedef short             INT16;
typedef int               INT32;
typedef unsigned int      UINT32;

#undef _INCLUDE_
#ifdef 		    _DEBUG_
#else
#define         mexPrintf   //
#endif
//input parameters declare
//data path input
#define VP_PH0_PARAM            prhs[0]
#define VP_PH1_PARAM            prhs[1]
#define VP_LR_PARAM             prhs[2]
#define VP_LOGO_PARAM           prhs[3]
//output parameters declare
#define VP_RESULT               plhs[0]

typedef struct {
	INT16*    cur_vector;
	INT16*    pre_vector;
	UINT32*   cur_sad;
	UINT32*   pre_sad;
	UINT8*    cur_apl;
	UINT8*    pre_apl;
	UINT16*   cur_dtl;
	UINT16*   pre_dtl;
	UINT16    block_number[2];
	UINT8     block_size[2];
	UINT8     temp_phase;
	UINT8     vec_precision[2];
	UINT8     vp_order;   //ss/ts/med/aav order
	bool      ss_en;      //spatial smooth: 1d tap5 lpf, 1/4, 3/16, 3/16, 3/16, 3/16
	UINT16    ss_thr;
	bool      ts_en;      //temporal smooth:
	UINT16    ts_thr;
	//UINT16    ts_vec_diff_thr;
	bool      med_en;    //median
	bool      med_mode;  //0:original 1:apl adaptive median
	UINT8     med_aam_apl_diff; //min/max diff in window
	//UINT8     med_aam_dtl_thr;  //detail in window threshold
	bool      aav_en;    //APL adjust vector:
	UINT8     aav_range;
	UINT8     aav_apl_consist_thr;
    UINT8     aav_apl_diff_thr;
    UINT16    aav_vec_diff_thr;
	//cuc
	UINT8     cuc_delta_thr;
	UINT8     cuc_dlt_diff_thr;
	bool      cuc_fill_en;
	UINT8     cuc_fill_lr_thr;//, uint8(4), ...
    UINT8     cuc_fill_thr;//', uint8(9), ...
    UINT8     cuc_rm_thr;//', uint8(4), ...
	bool      cuc_ext_en;
	bool      cuc_vec_rep_en;
	INT16*    cuc_pre_ph1_vec;
	UINT8*    cuc_pre_uncov_mask;
	bool      cuc_no_uc_overrep_en;
	UINT16    cuc_no_uc_overrep_thr;
	UINT8     cuc_uc_hit_cnt_thr;
	bool      cuc_sad_diff_en;
	UINT16    cuc_sad_diff_thr;
	//
} T_VP_PARAM;

typedef struct {
	//logo
	UINT8*    static_history;
	UINT8*    cont_motion_count;
	UINT8     logo_history_thr;
	UINT16    vec_static_thr;
	UINT16    vec_motion_thr;
    UINT8     static_inc_step;
	UINT8     motion_dec_step[4];
	UINT16    lr_nb55_noflat_thr;
	UINT16    lr_nb55_motion_thr;
	UINT8     fill_en;
	UINT8     ext_en;
	UINT8     logo_ext_thr;
	//cuc
	UINT8     retimer_phase;
	UINT16    good_vec_diff_thr;     
	UINT16    bad_vec_diff_thr;     
} T_COMMON_VP_PARAM;

UINT8 get_3x3_apl_neighbor(const UINT8* pAPL, const UINT16* pBlkNum, const UINT16* pCurBlk, UINT8 pNbAPL[3][3])
{
	int iBlkIdx[2];
	int iFetPos[2];
	UINT8 iMax, iMin;
	iMax = 0; iMin = 255;
	for(iBlkIdx[1]=-1; iBlkIdx[1]<=1; iBlkIdx[1]++)
		for(iBlkIdx[0]=-1; iBlkIdx[0]<=1; iBlkIdx[0]++)
		{
			iFetPos[0] = pCurBlk[0] + iBlkIdx[0];
			iFetPos[0] = iFetPos[0]<0? 0 : iFetPos[0]>=pBlkNum[0] ? pBlkNum[0]-1 : iFetPos[0];
			iFetPos[1] = pCurBlk[1] + iBlkIdx[1];
			iFetPos[1] = iFetPos[1]<0? 0 : iFetPos[1]>=pBlkNum[1] ? pBlkNum[1]-1 : iFetPos[1];
			pNbAPL[iBlkIdx[0]+1][iBlkIdx[1]+1] = pAPL[iFetPos[0]+pBlkNum[0]*iFetPos[1]];
			if(pNbAPL[iBlkIdx[0]+1][iBlkIdx[1]+1] > iMax) iMax = pNbAPL[iBlkIdx[0]+1][iBlkIdx[1]+1] ;
			if(pNbAPL[iBlkIdx[0]+1][iBlkIdx[1]+1] < iMin) iMin = pNbAPL[iBlkIdx[0]+1][iBlkIdx[1]+1] ;
		}

	return (iMax - iMin);
}

bool get_3x3_vec_neighbor(const INT16* pVec, const UINT16* pBlkNum, const UINT16* pCurBlk, INT16 pNbVec[3][3][2])
{
	int iBlkIdx[2];
	int iFetPos[2];
	for(iBlkIdx[1]=-1; iBlkIdx[1]<=1; iBlkIdx[1]++)
		for(iBlkIdx[0]=-1; iBlkIdx[0]<=1; iBlkIdx[0]++)
		{
			iFetPos[0] = pCurBlk[0] + iBlkIdx[0];
			iFetPos[0] = iFetPos[0]<0? 0 : iFetPos[0]>=pBlkNum[0] ? pBlkNum[0]-1 : iFetPos[0];
			iFetPos[1] = pCurBlk[1] + iBlkIdx[1];
			iFetPos[1] = iFetPos[1]<0? 0 : iFetPos[1]>=pBlkNum[1] ? pBlkNum[1]-1 : iFetPos[1];
			pNbVec[iBlkIdx[0]+1][iBlkIdx[1]+1][0] = pVec[iFetPos[0]+pBlkNum[0]*iFetPos[1]];
			pNbVec[iBlkIdx[0]+1][iBlkIdx[1]+1][1] = pVec[iFetPos[0]+pBlkNum[0]*iFetPos[1]+pBlkNum[0]*pBlkNum[1]];
		}
	return true;
}
INT16  i16abs(INT16 i)
{
	return i>0? i:-i;
}

bool vec_med5(INT16 pNbVec[3][3][2], INT16* pMedVec)
{
	INT16  iVec[5][2];
	INT16  iSz[5];
	UINT8  iOrd[5], iLoop, iIdx;
	INT16  i16Tmp;
    UINT8  ui8Tmp;
	iOrd[0] = 0; iOrd[1] = 1; iOrd[2] = 2; iOrd[3] = 3; iOrd[4] = 4;
	iVec[0][0] = pNbVec[1][0][0];
	iVec[0][1] = pNbVec[1][0][1];
	iSz[0] = i16abs(iVec[0][0] + iVec[0][1]);

	iVec[1][0] = pNbVec[1][2][0];
	iVec[1][1] = pNbVec[1][2][1];
	iSz[1] = i16abs(iVec[1][0] + iVec[1][1]);

	iVec[2][0] = pNbVec[0][1][0];
	iVec[2][1] = pNbVec[0][1][1];
	iSz[2] = i16abs(iVec[2][0] + iVec[2][1]);

	iVec[3][0] = pNbVec[2][1][0];
	iVec[3][1] = pNbVec[2][1][1];
	iSz[3] = i16abs(iVec[3][0] + iVec[3][1]);

	iVec[4][0] = pNbVec[1][1][0];
	iVec[4][1] = pNbVec[1][1][1];
	iSz[4] = i16abs(iVec[4][0] + iVec[4][1]);

	for(iLoop=0; iLoop<3; iLoop++)
	{
		for(iIdx=0; iIdx<4-iLoop; iIdx++)
		{
			if(iSz[iIdx] > iSz[iIdx+1])
			{
				i16Tmp = iSz[iIdx];
				iSz[iIdx] = iSz[iIdx+1];
				iSz[iIdx+1] = i16Tmp;
				ui8Tmp = iOrd[iIdx];
				iOrd[iIdx] = iOrd[iIdx+1];
				iOrd[iIdx+1] = ui8Tmp;
			}
		}
	}
	pMedVec[0] = iVec[iOrd[2]][0];
	pMedVec[1] = iVec[iOrd[2]][1];
    return true;
}

bool vp_med(const T_VP_PARAM* pParam,INT16* pVector)
{
	const UINT16* pBlkNum;
	const UINT8*  pAPL;

	UINT16  iBlkIdx[2];
	UINT8   pNbAPL[3][3];
	INT16   pNbVec[3][3][2];
	UINT8   iAPLDiff;
	INT16   pMedVec[2];


	bool    bEnableMed;

	INT16*  pOrgVec;
	int     iTotalBlkNum;

	if(!pParam->med_en) return true;

	pOrgVec = pParam->cur_vector;
	pBlkNum = pParam->block_number;
	pAPL    = pParam->cur_apl;

	if(!pParam->med_en) return true;
	
	iTotalBlkNum = pParam->block_number[0]*pParam->block_number[1];
	pOrgVec = (INT16*) malloc(2*iTotalBlkNum*sizeof(INT16));
	memcpy(pOrgVec, pVector, (sizeof(INT16))*iTotalBlkNum*2);

	for(iBlkIdx[1] = 0; iBlkIdx[1] < pBlkNum[1]; iBlkIdx[1] ++)
		for(iBlkIdx[0] = 0; iBlkIdx[0] < pBlkNum[0]; iBlkIdx[0] ++)
		{
			bEnableMed = true;
			if(pParam->med_mode)//aam enable
			{
				iAPLDiff = get_3x3_apl_neighbor(pAPL,pBlkNum,(const UINT16*)iBlkIdx, pNbAPL);
				if(iAPLDiff > pParam->med_aam_apl_diff) //not flat area
					bEnableMed = false;
				else
					bEnableMed = true;
			}
			if(bEnableMed)
			{
				get_3x3_vec_neighbor(pOrgVec, pBlkNum, iBlkIdx, pNbVec);
				vec_med5(pNbVec, pMedVec);
				pVector[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                       = pMedVec[0];
				pVector[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]] = pMedVec[1];
			}
		}

	free(pOrgVec);
	return true;
}

UINT8 ui8diff(UINT8 a, UINT8 b)
{
	return a>b?a-b:b-a;
}

INT16 i16diff(INT16 a, INT16 b)
{
	return a>b?a-b:b-a;
}

void get_hor_neighbor_vecs(const INT16* pVector, UINT8 iRange, int* iBlkIdx, const UINT16* pBlkNumber, INT16 pNeighborVector[32][2])
{
	int    iBlkPos[2];
	int    iVIdx;
	int    iTotalBlkNum;
	iBlkPos[1] = iBlkIdx[1];
	iTotalBlkNum = pBlkNumber[0]*pBlkNumber[1];
	for(iVIdx = -iRange; iVIdx<=iRange; iVIdx++)
	{
		iBlkPos[0] = iBlkIdx[0] + iVIdx;
		if(iBlkPos[0] >= pBlkNumber[0])
			iBlkPos[0] = pBlkNumber[0]-1;
		if(iBlkPos[0] <0)
			iBlkPos[0] = 0;
		pNeighborVector[iVIdx+iRange][0] = pVector[iBlkPos[0] + iBlkPos[1]*pBlkNumber[0]];
		pNeighborVector[iVIdx+iRange][1] = pVector[iBlkPos[0] + iBlkPos[1]*pBlkNumber[0] + iTotalBlkNum];
	}
}

void get_max_vec_diff(INT16 pNeighborVec[32][2], int* iMaxIdx, int iNum, int* pMaxVecDiff)
{
	int  iIdx, iABS;
	*pMaxVecDiff = 0;
	*iMaxIdx     = 0;
	for(iIdx=0; iIdx<iNum-1; iIdx++)
	{
		iABS = i16diff(pNeighborVec[iIdx][0],pNeighborVec[iIdx+1][0]) + 
			   i16diff(pNeighborVec[iIdx][1],pNeighborVec[iIdx+1][1]);
		if(iABS > (*pMaxVecDiff))
		{
			*pMaxVecDiff = iABS;
			*iMaxIdx     = iIdx;
		}
	}
}

void hor_adjust_vector(INT16* pVector, const INT16* pOrgVector, int iPosShift, int* iBlkIdx, const UINT16* iBlkNum)
{
	INT16  iVecX, iVecY;
	int    iFetPos[2];
	int    iIdx;

	if(iPosShift==0)
		return;
	else if(iPosShift>0)
	{
		iFetPos[0] = iBlkIdx[0] + iPosShift + 1;
		if(iFetPos[0] >= iBlkNum[0]) return;
		iFetPos[1] = iBlkIdx[1];
		iVecX = pOrgVector[iFetPos[0]+iFetPos[1]*iBlkNum[0]];
		iVecY = pOrgVector[iFetPos[0]+iFetPos[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]];
		for(iIdx=1; iIdx<=iPosShift; iIdx++)
		{
            pVector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iIdx] = iVecX;
			pVector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]+iIdx] = iVecY;
		}
	}
	else
	{
		iFetPos[0] = iBlkIdx[0] + iPosShift - 1;
		if(iFetPos[0] < 0) return;
		iFetPos[1] = iBlkIdx[1];
		iVecX = pOrgVector[iFetPos[0]+iFetPos[1]*iBlkNum[0]];
		iVecY = pOrgVector[iFetPos[0]+iFetPos[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]];
		for(iIdx=-1; iIdx>=iPosShift; iIdx--)
		{
			pVector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iIdx] = iVecX;
			pVector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]+iIdx] = iVecY;
		}
	}
}

void get_apl_left_right_range(UINT8* pAPL, const UINT16* pBlkNum, int iBlkPos[2], UINT8* pLeftRange, UINT8* pRightRange, UINT8 iRange)
{
	int  iBlkIdx[2];
	UINT8 iLeftMin, iLeftMax, iRightMin, iRightMax;

	iBlkIdx[1] = iBlkPos[1];
	
	iLeftMin = 255; iLeftMax = 0;
	iRightMin = 255; iRightMax = 0;
	for( iBlkIdx[0] = iBlkPos[0]-iRange; iBlkIdx[0] <=iBlkPos[0]; iBlkIdx[0]++)
	{
		if(iBlkIdx[0] < 0) continue;
		else 
		{
			if(iLeftMin > pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]) iLeftMin = pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]];
			if(iLeftMax < pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]) iLeftMax = pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]];
		}
	}
	for( iBlkIdx[0] = iBlkPos[0]+1; iBlkIdx[0] <=iBlkPos[0]+iRange; iBlkIdx[0]++)
	{
		if(iBlkIdx[0] >= pBlkNum[0]) continue;
		else 
		{
			if(iRightMin > pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]) iRightMin = pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]];
			if(iRightMax < pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]) iRightMax = pAPL[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]];
		}
	}
    *pRightRange = iRightMax - iRightMin;
    *pLeftRange  = iLeftMax  - iLeftMin;
}


bool vp_aav(const T_VP_PARAM* pParam,INT16* pVector)
{
	int     iBlkIdx[2];
	int     iBlkAdr, iBlkAdrY;
    UINT8*  pAPL;
	UINT8   iAPLLeft, iAPLRight;
	INT16   iNeighborVector[32][2];
	int     iMaxIdx;
	int     iMaxVecDiff;
	UINT8   iAPLLeftRange, iAPLRightRange;

	INT16*  pOrgVec;
	int     iTotalBlkNum;
	int     iShiftPos;

	pAPL = pParam->cur_apl;
	if(!pParam->aav_en) return true;

	iTotalBlkNum = pParam->block_number[0]*pParam->block_number[1];
	pOrgVec = (INT16*) malloc(2*iTotalBlkNum*sizeof(INT16));
	memcpy(pOrgVec, pVector, (sizeof(INT16))*iTotalBlkNum*2);

	for(iBlkIdx[1]=0; iBlkIdx[1]<pParam->block_number[1]; iBlkIdx[1]++)
		for(iBlkIdx[0]=4; iBlkIdx[0]<pParam->block_number[0]-4; iBlkIdx[0]++)
		{
			iBlkAdr  = iBlkIdx[0] + iBlkIdx[1] * pParam->block_number[0];
			iBlkAdrY = iBlkIdx[0] + iBlkIdx[1] * pParam->block_number[0]+
				       pParam->block_number[0]* pParam->block_number[1];
			iAPLLeft = pAPL[iBlkAdr]; iAPLRight = pAPL[iBlkAdr+1];
			get_apl_left_right_range(pAPL, pParam->block_number, iBlkIdx, &iAPLLeftRange, &iAPLRightRange, pParam->aav_range+2);
			if(ui8diff(iAPLLeft,iAPLRight)>pParam->aav_apl_diff_thr) //is apl edge area
			{
				get_hor_neighbor_vecs(pOrgVec, pParam->aav_range, iBlkIdx, pParam->block_number, iNeighborVector);
				get_max_vec_diff(iNeighborVector, &iMaxIdx, 2* pParam->aav_range+1, &iMaxVecDiff);
				iShiftPos = (iMaxIdx-pParam->aav_range);
				if(iMaxVecDiff > pParam->aav_vec_diff_thr && 
					(iShiftPos != 0)&&
					(iShiftPos>0?(iAPLRightRange< pParam->aav_apl_consist_thr):(iAPLLeftRange< pParam->aav_apl_consist_thr))
					)
					hor_adjust_vector(pVector, pOrgVec, (iMaxIdx - pParam->aav_range), iBlkIdx, pParam->block_number);
			}

		}

    free(pOrgVec);
	return true;
}

bool vp_ssmooth(const T_VP_PARAM* pParam,INT16* pVector)
{
	INT16*  pOrgVec;
	int     iTotalBlkNum;
	int     iBlkIdx[2], iNeighbor[2], iNbIdx;
	int     iMaxDiff, iDiff;
	INT16   iVecCt[2], iVecNb[2];
	int     iSumVec[2];
	int     iDebugLine;
	iTotalBlkNum = pParam->block_number[0]*pParam->block_number[1];
	if(pParam->ss_en) 
	{
		pOrgVec = (INT16*) malloc(2*iTotalBlkNum*sizeof(INT16));
		memcpy(pOrgVec, pVector, (sizeof(INT16))*iTotalBlkNum*2);
		for(iBlkIdx[1] = 0; iBlkIdx[1] < pParam->block_number[1]; iBlkIdx[1]++)
		{
			iDebugLine = iBlkIdx[1];
			for(iBlkIdx[0] = 3; iBlkIdx[0] < pParam->block_number[0]-3; iBlkIdx[0]++)
			{
				iMaxDiff = 0;
				iVecCt[0] = pOrgVec[iBlkIdx[0] + iBlkIdx[1]*pParam->block_number[0]];
				iVecCt[1] = pOrgVec[iBlkIdx[0] + iBlkIdx[1]*pParam->block_number[0] + iTotalBlkNum];
				iSumVec[0] = iVecCt[0]; iSumVec[1] = iVecCt[1];

				iNeighbor[1] = iBlkIdx[1];
				for(iNbIdx=-3 ; iNbIdx<=3; iNbIdx++)
				{
					iNeighbor[0] = iBlkIdx[0] + iNbIdx;
					iVecNb[0] = pOrgVec[iNeighbor[0] + iNeighbor[1]*pParam->block_number[0]];
					iVecNb[1] = pOrgVec[iNeighbor[0] + iNeighbor[1]*pParam->block_number[0] + iTotalBlkNum];
					iSumVec[0] += iVecNb[0]; iSumVec[1] = iVecNb[1];
					iDiff = i16abs(iVecNb[0]-iVecCt[0]) + i16abs(iVecNb[1]-iVecCt[1]);
					if(iDiff>iMaxDiff) iMaxDiff = iDiff;
				}
				if(iMaxDiff <= pParam->ss_thr)
				{
					pVector[iBlkIdx[0] + iBlkIdx[1]*pParam->block_number[0]] = iSumVec[0]/8;
					pVector[iBlkIdx[0] + iBlkIdx[1]*pParam->block_number[0] + iTotalBlkNum] = iSumVec[1]/8;
				}
			}
		}
		free(pOrgVec);
	}
	
	return true;
}

bool vp_tsmooth(const T_VP_PARAM* pParam,INT16* pVector)
{
	int     iTotalBlkNum;
	int     iBlkIdx[2];
	int     iDiff;

	INT16*  pPreVec = pParam->pre_vector;
	INT16*  pCurVec = pParam->cur_vector;
	iTotalBlkNum = pParam->block_number[0] * pParam->block_number[1];

	if(pParam->ts_en)
	{
		for(iBlkIdx[1] = 0; iBlkIdx[1]<pParam->block_number[1]; iBlkIdx[1]++)
			for(iBlkIdx[0] = 0; iBlkIdx[0]<pParam->block_number[0]; iBlkIdx[0]++)
			{
				iDiff = i16abs(pPreVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]] - pCurVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]]) +
					    i16abs(pPreVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0] + iTotalBlkNum] - pCurVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0] + iTotalBlkNum]);
				if(iDiff < pParam->ts_thr)
				{
					pVector[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]]                = (pPreVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]] + 
						                                                                     pCurVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]])/2;
					pVector[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0] + iTotalBlkNum] = (pPreVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]+ iTotalBlkNum] + 
						                                                                     pCurVec[iBlkIdx[0]+iBlkIdx[1]*pParam->block_number[0]+ iTotalBlkNum])/2;
				}
			}
	}

	return true;
}

bool logo_get_vec_st_history(const UINT16 iBlkIdx[2], INT16	iVecSize, const T_VP_PARAM* pPh0Param, const T_VP_PARAM* pPh1Param, const T_COMMON_VP_PARAM* pLogoParam, 
							 UINT8* pLogoStCount, UINT8* pLogoContMotCount)
{
    UINT16  iBlkNum[2];
	UINT32  iBlkAdr;
	UINT8   iLogoStaticCount, iContMotionCount;
	bool    bMotionBlk, bStaticBlk;
	iBlkNum[0] = pPh0Param->block_number[0]; iBlkNum[1] = pPh0Param->block_number[1];
	iBlkAdr = iBlkIdx[0] + iBlkNum[0]*iBlkIdx[1];
	//
	iLogoStaticCount = pLogoParam->static_history[iBlkAdr]; iContMotionCount = pLogoParam->cont_motion_count[iBlkAdr];
	bMotionBlk = iVecSize > pLogoParam->vec_motion_thr;
	bStaticBlk = iVecSize <= pLogoParam->vec_static_thr;
	if(bStaticBlk)
	{
		iLogoStaticCount += pLogoParam->static_inc_step;
		if(iLogoStaticCount > 63)
			iLogoStaticCount = 63;
	}
	else if(bMotionBlk)
	{
		if(iContMotionCount == 0)
		{
			iContMotionCount ++;
			if(iLogoStaticCount>=pLogoParam->motion_dec_step[0]) iLogoStaticCount -= pLogoParam->motion_dec_step[0];
			else iLogoStaticCount = 0;
		}
		else if(iContMotionCount == 1)
		{
			iContMotionCount ++;
            if(iLogoStaticCount>=pLogoParam->motion_dec_step[1]) iLogoStaticCount -= pLogoParam->motion_dec_step[1];
			else iLogoStaticCount = 0;
		}
		else if(iContMotionCount == 2)
		{
			iContMotionCount ++;
            if(iLogoStaticCount>=pLogoParam->motion_dec_step[2]) iLogoStaticCount -= pLogoParam->motion_dec_step[2];
			else iLogoStaticCount = 0;
		}
		else 
		{
			iContMotionCount = 3;
            if(iLogoStaticCount>=pLogoParam->motion_dec_step[3]) iLogoStaticCount -= pLogoParam->motion_dec_step[3];
			else iLogoStaticCount = 0;
		}

	}
	*pLogoStCount = iLogoStaticCount;
	*pLogoContMotCount = iContMotionCount;
	if(iLogoStaticCount > 63 || iContMotionCount > 3)
		mexPrintf("error @ %d, %d", iBlkIdx[0], iBlkIdx[1]);
	return true;
}

UINT16  logo_get_lr_motion(UINT16 iLRBlkIdx[2], const T_VP_PARAM* pLRParam)
{
	UINT8*  pAPL;
	UINT16  iBlkNum[2];
	UINT16  iSumDiff;
	UINT8   iBlkMot;
	INT8    iIdx[2];
	INT16   iBlkPos[2];
	iSumDiff = 0;
	iBlkNum[0] = pLRParam->block_number[0];  iBlkNum[1] = pLRParam->block_number[1];
	pAPL = pLRParam->cur_apl;
	for(iIdx[0] = -1; iIdx[0] <= 1; iIdx[0] ++)
	    for(iIdx[1] = -1; iIdx[1] <= 1; iIdx[1] ++)
		{
			iBlkPos[0] = iLRBlkIdx[0] + iIdx[0];
			if(iBlkPos[0] < 0) iBlkPos[0] = 0;
			else if(iBlkPos[0] > iBlkNum[0]-1) iBlkPos[0] = iBlkNum[0]-1;

			iBlkPos[1] = iLRBlkIdx[1] + iIdx[1];
			if(iBlkPos[1] < 0) iBlkPos[1] = 0;
			else if(iBlkPos[1] > iBlkNum[1]-1) iBlkPos[1] = iBlkNum[1]-1;

			iBlkMot = ui8diff(pLRParam->cur_apl[iBlkPos[0]+iBlkPos[1]*iBlkNum[0]], pLRParam->pre_apl[iBlkPos[0]+iBlkPos[1]*iBlkNum[0]]);
            if(iIdx[0]==0 && iIdx[1]==0)
				iBlkMot = 8*iBlkMot;
            iSumDiff += iBlkMot;
		}
	return (UINT16)(iSumDiff/16.0);
}

UINT16  logo_get_lr_detail(UINT16 iLRBlkIdx[2], const T_VP_PARAM* pLRParam)
{
	UINT16  iBlkNum[2];
	UINT32  iSumDiff;
	UINT16  iBlkDtl;
	INT8    iIdx[2];
	INT16   iBlkPos[2];
	iSumDiff = 0;
	iBlkNum[0] = pLRParam->block_number[0];  iBlkNum[1] = pLRParam->block_number[1];

	for(iIdx[0] = -1; iIdx[0] <= 1; iIdx[0] ++)
	    for(iIdx[1] = -1; iIdx[1] <= 1; iIdx[1] ++)
		{
			iBlkPos[0] = iLRBlkIdx[0] + iIdx[0];
			if(iBlkPos[0] < 0) iBlkPos[0] = 0;
			else if(iBlkPos[0] > iBlkNum[0]-1) iBlkPos[0] = iBlkNum[0]-1;

			iBlkPos[1] = iLRBlkIdx[1] + iIdx[1];
			if(iBlkPos[1] < 0) iBlkPos[1] = 0;
			else if(iBlkPos[1] > iBlkNum[1]-1) iBlkPos[1] = iBlkNum[1]-1;

            iBlkDtl = pLRParam->cur_dtl[iBlkPos[0]+iBlkPos[1]*iBlkNum[0]];

            if(iIdx[0]==0 && iIdx[1]==0)
				iBlkDtl = 8*iBlkDtl;
            
            iSumDiff += iBlkDtl;
		}
	return (UINT16)(iSumDiff/16.0);
}

bool logo_ext(const T_COMMON_VP_PARAM* pParam, UINT8* pMask, UINT16 iBlkNum[2])
{
	INT16  iBlkIdx[2], iNbIdx[2], iPos[2];
	UINT8* pOrgMsk;
	UINT8  iSumOfLogo;
	pOrgMsk = (UINT8*) malloc(iBlkNum[0]*iBlkNum[1]*sizeof(UINT8));
	memcpy(pOrgMsk, pMask, iBlkNum[0]*iBlkNum[1]);
	for(iBlkIdx[1] = 0; iBlkIdx[1]<iBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0] = 0; iBlkIdx[0] < iBlkNum[0]; iBlkIdx[0]++)
		{
			iSumOfLogo = 0;
			if(pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]])
				continue;
			else
			{
				for(iNbIdx[0] = -1; iNbIdx[0] <= 1; iNbIdx[0]++)
					for(iNbIdx[1] = -1; iNbIdx[1] <= 1; iNbIdx[1]++)
					{
						iPos[0] = iBlkIdx[0] + iNbIdx[0];
						if(iPos[0]>iBlkNum[0]-1)  iPos[0] = iBlkNum[0]-1;
						if(iPos[0]<0) iPos[0] = 0;

						iPos[1] = iBlkIdx[1] + iNbIdx[1];
						if(iPos[1]>iBlkNum[1]-1)  iPos[1] = iBlkNum[1]-1;
						if(iPos[1]<0) iPos[1] = 0;
						if(pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]])
							iSumOfLogo++;
				}
				if(iSumOfLogo>pParam->logo_ext_thr)
					pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 1;
			}
			
		}
	free(pOrgMsk);
    return true;
}

bool logo_fill(const T_COMMON_VP_PARAM* pParam, UINT8* pMask, UINT16 iBlkNum[2])
{
	INT16  iBlkIdx[2], iPos[2];
	UINT8* pOrgMsk;
	UINT8  iSumOfLogo;
	bool   bLeft, bRight, bTop, bBottom;
	pOrgMsk = (UINT8*) malloc(iBlkNum[0]*iBlkNum[1]*sizeof(UINT8));
	memcpy(pOrgMsk, pMask, iBlkNum[0]*iBlkNum[1]);
	for(iBlkIdx[1] = 1; iBlkIdx[1]<iBlkNum[1]-1; iBlkIdx[1]++)
		for(iBlkIdx[0] = 1; iBlkIdx[0] < iBlkNum[0]-1; iBlkIdx[0]++)
		{
			iSumOfLogo = 0;
			if(pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]])
				continue;
			else
			{
				bLeft = false; bRight = false;

				iPos[1] = iBlkIdx[1];
				iPos[0] = iBlkIdx[0] - 2;
                if(iPos[0]<0) iPos[0] = 0;
				bLeft |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];
				iPos[0] = iBlkIdx[0] - 1;
                if(iPos[0]<0) iPos[0] = 0;
				bLeft |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];

				iPos[0] = iBlkIdx[0] + 2;
                if(iPos[0]>iBlkNum[0]-1) iPos[0] = iBlkNum[0]-1;
				bRight |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];
				iPos[0] = iBlkIdx[0] + 1;
                if(iPos[0]>iBlkNum[0]-1) iPos[0] = iBlkNum[0]-1;
				bRight |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];

				if(bLeft & bRight)
				{
					pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 1;
					continue;
				}

				bTop = false; bBottom = false;

				iPos[0] = iBlkIdx[0];
				iPos[1] = iBlkIdx[1] - 2;
                if(iPos[1]<0) iPos[1] = 0;
				bTop |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];
				iPos[1] = iBlkIdx[1] - 1;
                if(iPos[1]<0) iPos[1] = 0;
				bTop |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];

				iPos[1] = iBlkIdx[1] + 2;
                if(iPos[1]>iBlkNum[1]-1) iPos[1] = iBlkNum[1]-1;
				bBottom |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];
				iPos[1] = iBlkIdx[1] + 1;
                if(iPos[1]>iBlkNum[1]-1) iPos[1] = iBlkNum[1]-1;
				bBottom |= pOrgMsk[iPos[0]+iPos[1]*iBlkNum[0]];

				if(bTop & bBottom)
				{
					pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 1;
					continue;
				}

			}
			
		}
	free(pOrgMsk);
    return true;
}


bool vp_logo(const T_VP_PARAM* pPh0Param, 
		     const T_VP_PARAM* pPh1Param, 
		     const T_VP_PARAM* pLRParam,
			 const T_COMMON_VP_PARAM* pLogoParam, 
			 UINT8* pMask, 
			 UINT8* pLogoHistory, UINT8* pConMotCnt, UINT8* pMotionArea, UINT8* pDetailArea)
{
	UINT16  iBlkIdx[2], iLRBlkIdx[2];
	UINT16  iBlkNum[2], iLRBlkNum[2], iBlkRatio[2];
	INT16   iVec[2];
	INT16   iVecSize;
	UINT16  iMotion,iDetail; 
	UINT8   iLogoStCount,iLogoContMotCount; 
	bool    bNotFlattenArea, bMotionArea;
	iBlkNum[0]   = pPh0Param->block_number[0]; iBlkNum[1]   = pPh0Param->block_number[1];
	iLRBlkNum[0] = pLRParam->block_number[0];  iLRBlkNum[1] = pLRParam->block_number[1];
	iBlkRatio[0] = pLRParam->block_size[0] /pPh0Param->block_size[0];
	iBlkRatio[1] = pLRParam->block_size[1] /pPh0Param->block_size[1];

	
	for(iBlkIdx[1] = 0; iBlkIdx[1]<iBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0] = 0; iBlkIdx[0]<iBlkNum[0]; iBlkIdx[0]++)
		{
			iLRBlkIdx[0] = (UINT16)floor(iBlkIdx[0]*1.0/iBlkRatio[0]+0.5);
			iLRBlkIdx[1] = (UINT16)floor(iBlkIdx[1]*1.0/iBlkRatio[1]+0.5);
			iVec[0]      = pPh0Param->cur_vector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]];
			iVec[1]      = pPh0Param->cur_vector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]];
			iVecSize     = i16abs(iVec[0]) + i16abs(iVec[1]);
			iVec[0]      = pPh1Param->cur_vector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]];
			iVec[1]      = pPh1Param->cur_vector[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]+iBlkNum[0]*iBlkNum[1]];
			iVecSize     += i16abs(iVec[0]) + i16abs(iVec[1]);
            
			logo_get_vec_st_history(iBlkIdx, iVecSize, pPh0Param, pPh1Param, pLogoParam, &iLogoStCount, &iLogoContMotCount);
			iMotion  = logo_get_lr_motion(iLRBlkIdx, pLRParam);
			iDetail  = logo_get_lr_detail(iLRBlkIdx, pLRParam);
			pLogoHistory[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = iLogoStCount;
			pConMotCnt[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]]   = iLogoContMotCount;

			bMotionArea        = iMotion > pLogoParam->lr_nb55_motion_thr;
			pMotionArea[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]]  = (UINT8)iMotion;//%bMotionArea;

			bNotFlattenArea    = iDetail > pLogoParam->lr_nb55_noflat_thr;
			pDetailArea[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]]  = (UINT8)iDetail;//bNotFlattenArea;
			pMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = bMotionArea && bNotFlattenArea && (iLogoStCount>pLogoParam->logo_history_thr);
			if(iLogoStCount > 63 || iLogoContMotCount > 3)
				mexPrintf("error @ %d, %d", iBlkIdx[0], iBlkIdx[1]);
		}


	if(pLogoParam->fill_en) logo_fill(pLogoParam, pMask, iBlkNum);
	if(pLogoParam->ext_en) logo_ext(pLogoParam, pMask, iBlkNum);
	return true;
}

bool vp_cuc(const T_VP_PARAM* pParam, const INT16* pPh0Vec, const INT16* pPh1Vec, bool bPh0, UINT8* pMask, INT16* pCUCVec)
{
	const UINT8*  pBlkSize  = pParam->block_size;
	const UINT16* pBlkNum   = pParam->block_number;
	const UINT8*  pPrecision= pParam->vec_precision;
	INT32   iTotalBlkNum = pBlkNum[0]*pBlkNum[1];

	const INT16*  pBaseVec  = bPh0? pPh0Vec : pPh1Vec;
	const INT16*  pRefVec   = bPh0? pPh1Vec : pPh0Vec;
	INT16   iSign     = bPh0? 1 : -1;

	UINT8*  pPreUncovMask = pParam->cuc_pre_uncov_mask;

	INT16   iVec[2], iRtVec[2], iRRtVec[2], iVecBlk[2];
	INT16   iBlkIdx[2], iRtBlkIdx[2];
	INT32   iIdxInPlane, iIdxInPlaneRt,iIdxInPlaneRRt ;
	INT16   iDelta1, iDelta2, iDeltaDiff;

	UINT8*  pTempMask;
	UINT8   iCntL, iCntR, iCnt;
	INT16   iNbIdx[2], iNbPos[2];

	UINT8   iPreUncovHitCnt, iPreUncovHitCntRRt;

	INT16   iVecCt[2];


	bool    bOOBx, bOOBy;
	bool	bCUCExt;

	INT16   iPreUCPh0VecDiff, iPreUCPh0VecDiffRRt;

	for(iBlkIdx[1] = 0; iBlkIdx[1]<pBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0] = 0; iBlkIdx[0]<pBlkNum[0]; iBlkIdx[0]++)
		{	iIdxInPlane = iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0];
			iVec[0] = pBaseVec[iIdxInPlane];
			iVec[1] = pBaseVec[iIdxInPlane+iTotalBlkNum];

			//retimer
			iVecBlk[0] = (INT16)(iVec[0]*1.0/pBlkSize[0]/pPrecision[0]);
			iVecBlk[1] = (INT16)(iVec[1]*1.0/pBlkSize[1]/pPrecision[1]);
			iRtBlkIdx[0] = iBlkIdx[0] + iSign*iVecBlk[0];
			bOOBx      = (iRtBlkIdx[0]<0) || (iRtBlkIdx[0]>pBlkNum[0]-1);
			iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:(iRtBlkIdx[0]>pBlkNum[0]-1)?(pBlkNum[0]-1):iRtBlkIdx[0];
			iRtBlkIdx[1] = iBlkIdx[1] + iSign*iVecBlk[1];
			bOOBy      = (iRtBlkIdx[1]<0) || (iRtBlkIdx[1]>pBlkNum[1]-1);
			iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:(iRtBlkIdx[1]>pBlkNum[1]-1)?(pBlkNum[1]-1):iRtBlkIdx[1];
			iIdxInPlane  = iRtBlkIdx[0]+iRtBlkIdx[1]*pBlkNum[0];
			iRtVec[0]    = bOOBx? 0:pRefVec[iIdxInPlane];
			iRtVec[1]    = bOOBy? 0:pRefVec[iIdxInPlane+iTotalBlkNum];
			//re-retimer
			iVecBlk[0]   = (INT16)(iRtVec[0]*1.0/pBlkSize[0]/pPrecision[0]);
			iVecBlk[1]   = (INT16)(iRtVec[1]*1.0/pBlkSize[1]/pPrecision[1]);
			iRtBlkIdx[0] = iBlkIdx[0] + iSign*iVecBlk[0];
			bOOBx      = (iRtBlkIdx[0]<0) || (iRtBlkIdx[0]>pBlkNum[0]-1);
			iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:(iRtBlkIdx[0]>pBlkNum[0]-1)?(pBlkNum[0]-1):iRtBlkIdx[0];
			iRtBlkIdx[1] = iBlkIdx[1] + iSign*iVecBlk[1];
			bOOBy      = (iRtBlkIdx[1]<0) || (iRtBlkIdx[1]>pBlkNum[1]-1);
			iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:(iRtBlkIdx[1]>pBlkNum[1]-1)?(pBlkNum[1]-1):iRtBlkIdx[1];
			iIdxInPlane  = iRtBlkIdx[0]+iRtBlkIdx[1]*pBlkNum[0];
			iRRtVec[0]   = bOOBx?0:pRefVec[iIdxInPlane];
			iRRtVec[1]   = bOOBy?0:pRefVec[iIdxInPlane+iTotalBlkNum];
			//delta calc
			iDelta1      = i16abs(iVec[0]-iRtVec[0])+i16abs(iVec[1]-iRtVec[1]);
			iDelta2      = i16abs(iRRtVec[0]-iRtVec[0])+i16abs(iRRtVec[1]-iRtVec[1]);
			iDeltaDiff   = i16abs(iDelta1-iDelta2);
			
			//mask
			iIdxInPlane = iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0];
			pMask[iIdxInPlane] = (iDelta1> pParam->cuc_delta_thr)&&
				                 (iDelta2> pParam->cuc_delta_thr)&&
								 (iDeltaDiff<pParam->cuc_dlt_diff_thr);
			if(pMask[iIdxInPlane])
				continue;

		}
		
		
	if(pParam->cuc_fill_en)
	{
		pTempMask = malloc(iTotalBlkNum*sizeof(UINT8));
		memcpy(pTempMask, pMask, iTotalBlkNum*sizeof(UINT8));

		for(iBlkIdx[1] = 0; iBlkIdx[1]<pBlkNum[1]; iBlkIdx[1]++)
			for(iBlkIdx[0] = 0; iBlkIdx[0]<pBlkNum[0]; iBlkIdx[0]++)
			{
				iCntL=iCntR=iCnt=0;
				for(iNbIdx[1] = -1; iNbIdx[1] <=1; iNbIdx[1]++)
					for(iNbIdx[0] = -2; iNbIdx[0] <=2; iNbIdx[0]++)
					{
						iNbPos[0] = iNbIdx[0] + iBlkIdx[0];
						iNbPos[0] = iNbPos[0] < 0 ? 0 : (iNbPos[0] > pBlkNum[0]-1) ? pBlkNum[0]-1 : iNbPos[0];
						iNbPos[1] = iNbIdx[1] + iBlkIdx[1];
						iNbPos[1] = iNbPos[1] < 0 ? 0 : (iNbPos[1] > pBlkNum[1]-1) ? pBlkNum[1]-1 : iNbPos[1];
						if(pTempMask[iBlkIdx[0]+iNbIdx[0]+(iBlkIdx[1]+iNbIdx[1])*pBlkNum[0]])
						{
							iCnt++;
							if(iNbIdx[0]<0)
								iCntL++;
							else if(iNbIdx[0]>0)
								iCntR++;
								
						}
					}

               if(iCnt>=pParam->cuc_fill_thr ||
				   iCntL>=pParam->cuc_fill_lr_thr && iCntR >= pParam->cuc_fill_lr_thr)
				   pMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]] = true;
			   else if(iCnt<= pParam->cuc_rm_thr)
					pMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]] = false;
			}
		free(pTempMask);
		
	}
	if(pParam->cuc_ext_en)
	{
		pTempMask = malloc(iTotalBlkNum*sizeof(UINT8));
		memcpy(pTempMask, pMask, iTotalBlkNum*sizeof(UINT8));
		for(iBlkIdx[1] = 0; iBlkIdx[1]<pBlkNum[1]; iBlkIdx[1]++)
			for(iBlkIdx[0] = 0; iBlkIdx[0]<pBlkNum[0]; iBlkIdx[0]++)
			{
				bCUCExt = false;
				for(iNbIdx[1] = -1; iNbIdx[1] <=1; iNbIdx[1]++)
				{
					for(iNbIdx[0] = -1; iNbIdx[0] <=1; iNbIdx[0]++)
					{
						iNbPos[0] = iNbIdx[0] + iBlkIdx[0];
						iNbPos[0] = iNbPos[0] < 0 ? 0 : (iNbPos[0] > pBlkNum[0]-1) ? pBlkNum[0]-1 : iNbPos[0];
						iNbPos[1] = iNbIdx[1] + iBlkIdx[1];
						iNbPos[1] = iNbPos[1] < 0 ? 0 : (iNbPos[1] > pBlkNum[1]-1) ? pBlkNum[1]-1 : iNbPos[1];
						if(pTempMask[iBlkIdx[0]+iNbIdx[0]+(iBlkIdx[1]+iNbIdx[1])*pBlkNum[0]])
						{
							bCUCExt = true;
							break;
						}
					}
					if (bCUCExt) break;
				}
				if(bCUCExt)
					pMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]] = true;
			}
		free(pTempMask);
	}

	for(iBlkIdx[1] = 0; iBlkIdx[1]<pBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0] = 0; iBlkIdx[0]<pBlkNum[0]; iBlkIdx[0]++)
		{
			iIdxInPlane = iBlkIdx[0] + iBlkIdx[1]*pBlkNum[0];
			if(bPh0 & pMask[iIdxInPlane]) //cover area, direct take from VecPh1(n-1)
			{
				pCUCVec[iIdxInPlane]              = pParam->cuc_pre_ph1_vec[iIdxInPlane];
				pCUCVec[iIdxInPlane+iTotalBlkNum] = pParam->cuc_pre_ph1_vec[iIdxInPlane+iTotalBlkNum];
			}
			else if((~bPh0)& pMask[iIdxInPlane])//uncover area,
			{
				iVec[0] = pBaseVec[iIdxInPlane];
				iVec[1] = pBaseVec[iIdxInPlane+iTotalBlkNum];
				//retimer
				iVecBlk[0] = (INT16)(iVec[0]*1.0/pBlkSize[0]/pPrecision[0]);
				iVecBlk[1] = (INT16)(iVec[1]*1.0/pBlkSize[1]/pPrecision[1]);
				iPreUncovHitCnt = 0;
				for(iNbIdx[0] = -1; iNbIdx[0] <=1; iNbIdx[0]++)
					for(iNbIdx[1] = -1; iNbIdx[1] <=1; iNbIdx[1]++)
					{
						iNbPos[0] = iBlkIdx[0]+iNbIdx[0];
						iNbPos[1] = iBlkIdx[1]+iNbIdx[1];

						iRtBlkIdx[0] = iNbPos[0] + iSign*iVecBlk[0];
						iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
						iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];

						iRtBlkIdx[1] = iNbPos[1] + iSign*iVecBlk[1];
						iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
						iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];

						iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
						if(pPreUncovMask[iIdxInPlaneRt]) iPreUncovHitCnt++;
					}

				//ct
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iVecCt[0] = pPh0Vec[iIdxInPlaneRt];
				iVecCt[1] = pPh0Vec[iIdxInPlaneRt+iTotalBlkNum];
				//left
				iNbPos[0] = iBlkIdx[0] - 1 + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiff = i16abs(pPh0Vec[iIdxInPlaneRt] - iVecCt[0]);
				
				//right
				iNbPos[0] = iBlkIdx[0] + 1 + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiff = (i16abs(pPh0Vec[iIdxInPlaneRt] - iVecCt[0])>iPreUCPh0VecDiff) ? i16abs(pPh0Vec[iIdxInPlaneRt] - iVecCt[0]) : iPreUCPh0VecDiff;

				//up
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] - 1 + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiff = (i16abs(pPh0Vec[iIdxInPlaneRt+iTotalBlkNum] - iVecCt[1])>iPreUCPh0VecDiff) ? i16abs(pPh0Vec[iIdxInPlaneRt+iTotalBlkNum] - iVecCt[1]) : iPreUCPh0VecDiff;


				//dn
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + 1 + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiff = (i16abs(pPh0Vec[iIdxInPlaneRt+iTotalBlkNum] - iVecCt[1])>iPreUCPh0VecDiff) ? i16abs(pPh0Vec[iIdxInPlaneRt+iTotalBlkNum] - iVecCt[1]) : iPreUCPh0VecDiff;


				iRtBlkIdx[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
////////////
				iVec[0] = pBaseVec[iIdxInPlaneRt];
				iVec[1] = pBaseVec[iIdxInPlaneRt+iTotalBlkNum];
				//retimer
				iVecBlk[0] = (INT16)(iVec[0]*1.0/pBlkSize[0]/pPrecision[0]);
				iVecBlk[1] = (INT16)(iVec[1]*1.0/pBlkSize[1]/pPrecision[1]);
				iPreUncovHitCntRRt = 0;
				for(iNbIdx[0] = -1; iNbIdx[0] <=1; iNbIdx[0]++)
					for(iNbIdx[1] = -1; iNbIdx[1] <=1; iNbIdx[1]++)
					{
						iNbPos[0] = iBlkIdx[0]+iNbIdx[0];
						iNbPos[1] = iBlkIdx[1]+iNbIdx[1];

						iRtBlkIdx[0] = iNbPos[0] + iSign*iVecBlk[0];
						iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
						iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];

						iRtBlkIdx[1] = iNbPos[1] + iSign*iVecBlk[1];
						iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
						iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];

						iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
						if(pPreUncovMask[iIdxInPlaneRRt]) iPreUncovHitCntRRt++;
					}

				//ct
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iVecCt[0] = pPh0Vec[iIdxInPlaneRRt];
				iVecCt[1] = pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum];
				//left
				iNbPos[0] = iBlkIdx[0] - 1 + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiffRRt = i16abs(pPh0Vec[iIdxInPlaneRRt] - iVecCt[0]);
				
				//right
				iNbPos[0] = iBlkIdx[0] + 1 + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiffRRt = (i16abs(pPh0Vec[iIdxInPlaneRRt] - iVecCt[0])>iPreUCPh0VecDiffRRt) ? i16abs(pPh0Vec[iIdxInPlaneRRt] - iVecCt[0]) : iPreUCPh0VecDiffRRt;

				//up
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] - 1 + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiffRRt = (i16abs(pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum] - iVecCt[1])>iPreUCPh0VecDiffRRt) ? i16abs(pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum] - iVecCt[1]) : iPreUCPh0VecDiffRRt;


				//dn
				iNbPos[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iNbPos[1] = iBlkIdx[1] + 1 + iSign*iVecBlk[1];
				iRtBlkIdx[0] = iNbPos[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iNbPos[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];
				iPreUCPh0VecDiffRRt = (i16abs(pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum] - iVecCt[1])>iPreUCPh0VecDiffRRt) ? i16abs(pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum] - iVecCt[1]) : iPreUCPh0VecDiffRRt;


				iRtBlkIdx[0] = iBlkIdx[0] + iSign*iVecBlk[0];
				iRtBlkIdx[0] = (iRtBlkIdx[0]<0)?0:iRtBlkIdx[0]; 
				iRtBlkIdx[0] = (iRtBlkIdx[0]>(pBlkNum[0]-1))?(pBlkNum[0]-1):iRtBlkIdx[0];
				iRtBlkIdx[1] = iBlkIdx[1] + iSign*iVecBlk[1];
				iRtBlkIdx[1] = (iRtBlkIdx[1]<0)?0:iRtBlkIdx[1]; 
				iRtBlkIdx[1] = (iRtBlkIdx[1]>(pBlkNum[1]-1))?(pBlkNum[1]-1):iRtBlkIdx[1];
				iIdxInPlaneRRt = iRtBlkIdx[0] +iRtBlkIdx[1]*pBlkNum[0];

				
				if(iPreUncovHitCnt > pParam->cuc_uc_hit_cnt_thr) //fetch a uncover area in previous uncover area
				{
					if((!pParam->cuc_no_uc_overrep_en) ||
						(pParam->cuc_no_uc_overrep_en && (iPreUCPh0VecDiff<pParam->cuc_no_uc_overrep_thr)))
					{
						pCUCVec[iIdxInPlane] = pPh0Vec[iIdxInPlaneRt];
						pCUCVec[iIdxInPlane+iTotalBlkNum] = pPh0Vec[iIdxInPlaneRt+iTotalBlkNum];
					}
				}
				else if(iPreUncovHitCntRRt > pParam->cuc_uc_hit_cnt_thr)
				{
					if((!pParam->cuc_no_uc_overrep_en) ||
						(pParam->cuc_no_uc_overrep_en && (iPreUCPh0VecDiff<pParam->cuc_no_uc_overrep_thr)))
					{
						pCUCVec[iIdxInPlane] = pPh0Vec[iIdxInPlaneRRt];
						pCUCVec[iIdxInPlane+iTotalBlkNum] = pPh0Vec[iIdxInPlaneRRt+iTotalBlkNum];
					}
				}
			}
		}

	return true;
}

INT16 i16med3(INT16 dat1, INT16 dat2, INT16 dat3)
{
	if     (dat1<=dat2 &&  dat1 >= dat3 || dat1<=dat3 && dat1>=dat2) return dat1;
	else if(dat2<=dat1 &&  dat2 >= dat3 || dat2<=dat3 && dat2>=dat1) return dat2;
	else                                                             return dat3;
}


bool 	vp_retimer(const T_COMMON_VP_PARAM* pCommonParam, const T_VP_PARAM* pPh0Param, const T_VP_PARAM* pPh1Param, const T_VP_PARAM* pLRParam, 
				   INT8* pCUCMaskPh0, INT8* pCUCMaskPh1, const INT16* pPh0CUCVec, const INT16* pPh1CUCVec, INT8* pCUCMask, INT16* pMCVec)
{
	INT16             iBlkIdx[2], iLRPos[2], iRtPos[2], iVecBlk[2];
	const UINT16      *pBlkNum, *pLRBlkNum;
	const UINT8       *pBlkSize, *pLRBlkSize; 
	const UINT8       *pPrecision;
	UINT8             iLRRatio[2];
	const INT16       *pLRVec;
	INT16             iLRVec[2], iPh0RtVec[2], iPh1RtVec[2];
	UINT8             iTempPhase;
	bool              bCover, bUncover;
	INT16             iSumDiff;
	UINT16            iPh0RtCurSAD,iPh0RtPreSAD;
	
	pLRVec = pLRParam->cur_vector;

	pBlkNum = pPh0Param->block_number;
	pLRBlkNum = pLRParam->block_number;
	pBlkSize  = pPh0Param->block_size;
	pLRBlkSize = pLRParam->block_size;
	iLRRatio[0] = pLRBlkSize[0]/pBlkSize[0];
	iLRRatio[1] = pLRBlkSize[1]/pBlkSize[1];
	pPrecision = pPh0Param->vec_precision;
	//iTempPhase = pLRParam->temp_phase;
	iTempPhase = pCommonParam->retimer_phase;

	for(iBlkIdx[1]=0; iBlkIdx[1]<pBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0]=0; iBlkIdx[0]<pBlkNum[0]; iBlkIdx[0]++)
		{
			iLRPos[0] = (INT16)(iBlkIdx[0]*1.0/iLRRatio[0]);
			iLRPos[1] = (INT16)(iBlkIdx[1]*1.0/iLRRatio[1]);
			iLRVec[0] = pLRVec[iLRPos[0] + iLRPos[1]*pLRBlkNum[0]]*iLRRatio[0];
			iLRVec[1] = pLRVec[iLRPos[0] + iLRPos[1]*pLRBlkNum[0] + pLRBlkNum[0]*pLRBlkNum[1]]*iLRRatio[0];
            //rt to ph0
			iVecBlk[0] = (INT16)(-1.0*iLRVec[0]*iTempPhase/128/pPrecision[0]/pBlkSize[0]);
			iVecBlk[1] = (INT16)(-1.0*iLRVec[1]*iTempPhase/128/pPrecision[1]/pBlkSize[1]);
			iRtPos[0] = iBlkIdx[0]+iVecBlk[0]; iRtPos[0] = (iRtPos[0]<0)?0:(iRtPos[0]>pBlkNum[0]-1)?pBlkNum[0]-1:iRtPos[0];
			iRtPos[1] = iBlkIdx[1]+iVecBlk[1]; iRtPos[1] = (iRtPos[1]<0)?0:(iRtPos[1]>pBlkNum[1]-1)?pBlkNum[1]-1:iRtPos[1];
			iPh0RtVec[0] = pPh0CUCVec[iRtPos[0]+iRtPos[1]*pBlkNum[0]];
			iPh0RtVec[1] = pPh0CUCVec[iRtPos[0]+iRtPos[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]];
			iPh0RtCurSAD = pPh0Param->cur_sad[iRtPos[0]+iRtPos[1]*pBlkNum[0]];
			iPh0RtPreSAD = pPh0Param->pre_sad[iRtPos[0]+iRtPos[1]*pBlkNum[0]];
			bCover       = pCUCMaskPh0[iRtPos[0]+iRtPos[1]*pBlkNum[0]]&&(pPh0Param->cuc_sad_diff_en?(iPh0RtPreSAD<iPh0RtCurSAD- pPh0Param->cuc_sad_diff_thr):1);
			//rt to ph1
			iVecBlk[0] = (INT16)(1.0*iLRVec[0]*(128-iTempPhase)/128/pPrecision[0]/pBlkSize[0]);
			iVecBlk[1] = (INT16)(1.0*iLRVec[1]*(128-iTempPhase)/128/pPrecision[1]/pBlkSize[1]);
			iRtPos[0] = iBlkIdx[0]+iVecBlk[0]; iRtPos[0] = (iRtPos[0]<0)?0:(iRtPos[0]>pBlkNum[0]-1)?pBlkNum[0]-1:iRtPos[0];
			iRtPos[1] = iBlkIdx[1]+iVecBlk[1]; iRtPos[1] = (iRtPos[1]<0)?0:(iRtPos[1]>pBlkNum[1]-1)?pBlkNum[1]-1:iRtPos[1];
			iPh1RtVec[0] = pPh1CUCVec[iRtPos[0]+iRtPos[1]*pBlkNum[0]];
			iPh1RtVec[1] = pPh1CUCVec[iRtPos[0]+iRtPos[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]];
			bUncover     = pCUCMaskPh1[iRtPos[0]+iRtPos[1]*pBlkNum[0]];
            
			
			//determin
		
			if(bCover & !bUncover)//cover area
			{
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                       = iPh0RtVec[0];
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]] = iPh0RtVec[1];
				pCUCMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                     = -1;
			} 
			else if(!bCover & bUncover)//uncover area
			{
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                       = iPh1RtVec[0];
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]] = iPh1RtVec[1];
				pCUCMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                     = 1;
			}
			else if(bCover & bUncover)//cuc conflict area
			{
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                       = iLRVec[0];
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]] = iLRVec[1];
				pCUCMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                     = 7;
			}
			else //not cover/uncover area
			{
				//use med3 to protect small object
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                       = i16med3(iLRVec[0], iPh0RtVec[0], iPh1RtVec[0]);
				pMCVec[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]+pBlkNum[0]*pBlkNum[1]] = i16med3(iLRVec[1], iPh0RtVec[1], iPh1RtVec[1]);
				iSumDiff = i16abs(iLRVec[0]-iPh0RtVec[0]) + i16abs(iLRVec[1]-iPh0RtVec[1]) +
                           i16abs(iPh0RtVec[0]-iPh1RtVec[0]) + i16abs(iPh0RtVec[1]-iPh1RtVec[1]) +
                           i16abs(iPh0RtVec[0]-iPh1RtVec[0]) + i16abs(iPh0RtVec[1]-iPh1RtVec[1]);
				pCUCMask[iBlkIdx[0]+iBlkIdx[1]*pBlkNum[0]]                     = (iSumDiff <= pCommonParam->good_vec_diff_thr) ? 0: 
					                                                             (iSumDiff>= pCommonParam->bad_vec_diff_thr)   ? 5 : 3;
			}


		}

	return true;
}

bool vp(const T_VP_PARAM* pPh0Param, 
		const T_VP_PARAM* pPh1Param, 
		const T_VP_PARAM* pLRParam, 
		const T_COMMON_VP_PARAM* pLogoParam,
		INT16* pMCVec, INT16* pPh0Vec, INT16* pPh0CUCVec, INT16* pPh1Vec, INT16* pPh1CUCVec, INT16* pLRVec, 
		UINT8* pLogoMask, UINT8* pCovMask, UINT8* pUncovMask, INT8* pCUCMask, UINT8* pObjMask, 
		UINT8* pLogoHistory, UINT8* pConMotCnt, UINT8* pMotionArea, UINT8* pDetailArea)
{
	UINT32  ui32BlkNum, ui32LRBlkNum;
	//INT8    *pCUCMaskPh0, *pCUCMaskPh1;
	//INT16*  pPh0CUCVec, pPh1CUCVec;
	ui32BlkNum   = pPh0Param->block_number[0]*pPh0Param->block_number[1];
	ui32LRBlkNum = pLRParam->block_number[0] *pLRParam->block_number[1];
	

	memcpy(pPh0Vec, pPh0Param->cur_vector, (sizeof(INT16))*ui32BlkNum*2);
	memcpy(pPh1Vec, pPh1Param->cur_vector, (sizeof(INT16))*ui32BlkNum*2);
	memcpy(pLRVec, pLRParam->cur_vector, (sizeof(INT16))*ui32LRBlkNum*2);
	memcpy(pPh0CUCVec, pPh0Vec, (sizeof(INT16))*ui32BlkNum*2);
	memcpy(pPh1CUCVec, pPh1Vec, (sizeof(INT16))*ui32BlkNum*2);

		
	switch(pPh0Param->vp_order)
	{
		//     	median                    APL adjust vector          spatial smooth                 temporal smooth
		case 0 :vp_med(pPh0Param, pPh0Vec);vp_aav(pPh0Param, pPh0Vec)    ;vp_ssmooth(pPh0Param, pPh0Vec);vp_tsmooth(pPh0Param, pPh0Vec); break;
		case 1 :vp_aav(pPh0Param, pPh0Vec);vp_med(pPh0Param, pPh0Vec)    ;vp_ssmooth(pPh0Param, pPh0Vec);vp_tsmooth(pPh0Param, pPh0Vec); break;
		case 2 :vp_aav(pPh0Param, pPh0Vec);vp_ssmooth(pPh0Param, pPh0Vec);vp_tsmooth(pPh0Param, pPh0Vec);vp_med(pPh0Param, pPh0Vec)    ; break;
		default:vp_med(pPh0Param, pPh0Vec);vp_aav(pPh0Param, pPh0Vec)    ;vp_ssmooth(pPh0Param, pPh0Vec);vp_tsmooth(pPh0Param, pPh0Vec); break;
	}

	switch(pPh1Param->vp_order)
	{
		//     	median                    APL adjust vector          spatial smooth                 temporal smooth
		case 0 :vp_med(pPh1Param, pPh1Vec);vp_aav(pPh1Param, pPh1Vec)    ;vp_ssmooth(pPh1Param, pPh1Vec);vp_tsmooth(pPh1Param, pPh1Vec); break;
		case 1 :vp_aav(pPh1Param, pPh1Vec);vp_med(pPh1Param, pPh1Vec)    ;vp_ssmooth(pPh1Param, pPh1Vec);vp_tsmooth(pPh1Param, pPh1Vec); break;
		case 2 :vp_aav(pPh1Param, pPh1Vec);vp_ssmooth(pPh1Param, pPh1Vec);vp_tsmooth(pPh1Param, pPh1Vec);vp_med(pPh1Param, pPh1Vec)    ; break;
		default:vp_med(pPh1Param, pPh1Vec);vp_aav(pPh1Param, pPh1Vec)    ;vp_ssmooth(pPh1Param, pPh1Vec);vp_tsmooth(pPh1Param, pPh1Vec); break;
	}

	switch(pLRParam->vp_order)
	{
		//     	median                    APL adjust vector          spatial smooth                 temporal smooth
		case 0:vp_med(pLRParam, pLRVec);vp_aav(pLRParam, pLRVec);vp_ssmooth(pLRParam, pLRVec);vp_tsmooth(pLRParam, pLRVec); break;
		case 1:vp_aav(pLRParam, pLRVec);vp_med(pLRParam, pLRVec);vp_ssmooth(pLRParam, pLRVec);vp_tsmooth(pLRParam, pLRVec); break;
		case 2:vp_aav(pLRParam, pLRVec);vp_ssmooth(pLRParam, pLRVec);vp_tsmooth(pLRParam, pLRVec);vp_med(pLRParam, pLRVec); break;
		default:vp_med(pLRParam, pLRVec);vp_aav(pLRParam, pLRVec);vp_ssmooth(pLRParam, pLRVec);vp_tsmooth(pLRParam, pLRVec); break;
	}

	//logo detect
	vp_logo(pPh0Param, pPh1Param, pLRParam, pLogoParam, pLogoMask, pLogoHistory, pConMotCnt, pMotionArea, pDetailArea);

	//cuc
	//pCUCMaskPh0 = malloc(sizeof(UINT8) * ui32BlkNum);
	//pCUCMaskPh1 = malloc(sizeof(UINT8) * ui32BlkNum);

	vp_cuc(pPh0Param, (const INT16*)pPh0Vec, (const INT16*)pPh1Vec, true , pCovMask, pPh0CUCVec);//cover detect
	vp_cuc(pPh1Param, (const INT16*)pPh0Vec, (const INT16*)pPh1Vec, false, pUncovMask, pPh1CUCVec);//uncover detect

	//retimer
	vp_retimer(pLogoParam, pPh0Param, pPh1Param, pLRParam, pCovMask, pUncovMask, (const INT16*) pPh0CUCVec, (const INT16*) pPh1CUCVec, pCUCMask, pMCVec);
	//free(pCUCMaskPh0); free(pCUCMaskPh1);

	//obj
	//vp_obj(pPh0Param, pPh1Param, pLRParam, pObjMask);
	return true;
}


bool   parser_logo_parameters(const mxArray* pmxaParam, T_COMMON_VP_PARAM* pParam)
 {

	 //logo
	char         sStHistory         [32] = "static_history";
	char         sContinueMotCnt    [32] = "cont_motion_count";
	char         sVecStThr          [32] = "vec_static_thr";
	char         sVecMotThr         [32] = "vec_motion_thr";
	char         sLogoHistoryThr    [32] = "logo_history_thr";
	char         sStaticIncStep     [32] = "static_inc_step";
	char         sMotionDecStep     [32] = "motion_dec_step";
	char         sLr55NoflatThr     [32] = "lr_nb55_noflat_thr";
	char         sLr55MotionThr     [32] = "lr_nb55_motion_thr";
	char         sFillEn            [32] = "fill_en";     //UINT8     fill_en;
	char         sExtEn             [32] = "ext_en";      //UINT8     ext_en;
	char         sLogoExtThr        [32] = "logo_ext_thr";//UINT8     logo_ext_thr;
	//cuc
	char         sRetimerPhase      [32] = "retimer_phase";//UINT8     temp_phase;
	char         sGoodVecDiffThr    [32] = "good_vec_diff_thr"; //UINT16    good_vec_diff_thr;     
	char         sBadVecDiffThr     [32] = "bad_vec_diff_thr";  //UINT16    bad_vec_diff_thr;  		
	
	

	mxArray *    pmxaTemp;
	UINT8*       pui8Temp;
	UINT16*      pui16Temp;
	//INT16*       pi16Temp;
	//UINT32*      pui32Temp;

	mexPrintf("parser vp-logo parameters\n");
	//UINT8*    static_history;
	pmxaTemp = mxGetField(pmxaParam, 0, sStHistory);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->static_history  = pui8Temp;
	mexPrintf("static_history: @%H\n", pParam->static_history);

	//UINT8*    cont_motion_count;
	pmxaTemp = mxGetField(pmxaParam, 0, sContinueMotCnt);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cont_motion_count  = pui8Temp;
	mexPrintf("cont_motion_count: @%H\n", pParam->cont_motion_count);

	//UINT16    vec_static_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sVecStThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->vec_static_thr  = pui16Temp[0];
	mexPrintf("vec_static_thr: %d\n", pParam->vec_static_thr);

	//UINT16    vec_motion_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sVecMotThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->vec_motion_thr  = pui16Temp[0];
	mexPrintf("vec_motion_thr: %d\n", pParam->vec_motion_thr);

	//UINT8	  sLogoHistoryThr    [32] = "logo_history_thr";
	pmxaTemp = mxGetField(pmxaParam, 0, sLogoHistoryThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->logo_history_thr  = pui8Temp[0];
	mexPrintf("logo_history_thr: %d\n", pParam->logo_history_thr);

	//UINT8   sStaticIncStep     [32] = "static_inc_step";
	pmxaTemp = mxGetField(pmxaParam, 0, sStaticIncStep);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->static_inc_step  = pui8Temp[0];
	mexPrintf("static_inc_step: %d\n", pParam->static_inc_step);

	//UINT8   sMotionDecStep     [32] = "motion_dec_step";
	pmxaTemp = mxGetField(pmxaParam, 0, sMotionDecStep);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->motion_dec_step[0]  = pui8Temp[0];
	pParam->motion_dec_step[1]  = pui8Temp[1];
	pParam->motion_dec_step[2]  = pui8Temp[2];
	pParam->motion_dec_step[3]  = pui8Temp[3];
	mexPrintf("motion_dec_step: %d\n", pParam->motion_dec_step);


	//UINT16    lr_nb55_noflat_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sLr55NoflatThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->lr_nb55_noflat_thr  = pui16Temp[0];
	mexPrintf("lr_nb55_noflat_thr: %d\n", pParam->lr_nb55_noflat_thr);

	//UINT16    lr_nb55_motion_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sLr55MotionThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->lr_nb55_motion_thr  = pui16Temp[0];
	mexPrintf("lr_nb55_motion_thr: %d\n", pParam->lr_nb55_motion_thr);

	//UINT8     fill_en;
	pmxaTemp = mxGetField(pmxaParam, 0, sFillEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->fill_en  = pui8Temp[0];
	mexPrintf("fill_en: %d\n", pParam->fill_en);

	//UINT8     ext_en;
	pmxaTemp = mxGetField(pmxaParam, 0, sExtEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->ext_en  = pui8Temp[0];
	mexPrintf("ext_en: %d\n", pParam->ext_en);

	//UINT8     logo_ext_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sLogoExtThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->logo_ext_thr  = pui8Temp[0];
	mexPrintf("logo_ext_thr: %d\n", pParam->logo_ext_thr);

	//cuc
	//UINT8     retimer_phase;
	pmxaTemp = mxGetField(pmxaParam, 0, sRetimerPhase);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->retimer_phase  = pui8Temp[0];
	mexPrintf("retimer_phase: %d\n", pParam->retimer_phase);
	//UINT16    good_vec_diff_thr;     
	pmxaTemp = mxGetField(pmxaParam, 0, sGoodVecDiffThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->good_vec_diff_thr  = pui16Temp[0];
	mexPrintf("good_vec_diff_thr: %d\n", pParam->good_vec_diff_thr);
	//UINT16    bad_vec_diff_thr;  		
	pmxaTemp = mxGetField(pmxaParam, 0, sBadVecDiffThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->bad_vec_diff_thr  = pui16Temp[0];
	mexPrintf("bad_vec_diff_thr: %d\n", pParam->bad_vec_diff_thr);

	return true;

 }



bool   parser_vp_parameters(const mxArray* pmxaParam, T_VP_PARAM* pParam)
 {
 
	char         sCurVector         [32] = "cur_vector";
	char         sCurSAD            [32] = "cur_sad";
	char         sCurAPL            [32] = "cur_apl";
	char         sCurDtl            [32] = "cur_dtl";
	char         sPreVector         [32] = "pre_vector";
	char         sPreSAD            [32] = "pre_sad";
	char         sPreAPL            [32] = "pre_apl";
	char         sPreDtl            [32] = "pre_dtl";
	char         sBlkNum            [32] = "block_number";
	char         sBlkSz             [32] = "block_size";
	char         sTempPhase         [32] = "temp_phase";
	char         sVecPrecision      [32] = "vec_precision";
	char         sVpOrder           [32] = "vp_order";
    //spatial smooth
    char         sSSEn              [32] = "ss_en";
	char         sSSThr             [32] = "ss_thr";
	//temporal smooth
	char         sTSEn              [32] = "ts_en";
	char         sTSThr             [32] = "ts_thr";
	//median
	char         sMedEn             [32] = "med_en";
	char         sMedMode           [32] = "med_mode";
	char         sMedAAMAplDiff     [32] = "med_aam_apl_diff";
	//APL adjust vector
	char         sAAVEn             [32] = "aav_en";
	char         sAAVRange          [32] = "aav_range";
	char         sAAVAplConsisThr   [32] = "aav_apl_consist_thr";
	char         sAAVAplDiffThr     [32] = "aav_apl_diff_thr";
	char         sAAVVecDiffThr     [32] = "aav_vec_diff_thr";
	//cuc
	char         sCUCDltThr         [32] = "cuc_delta_thr"; //UINT8     ;
	char         sCUCDltDiffThr     [32] = "cuc_dlt_diff_thr"; //UINT8;
	char         sCUCFillEn         [32] = "cuc_fill_en"; //bool;
	char         sCUCFillLRTh       [32] = "cuc_fill_lr_thr"; //UINT8     cuc_fill_lr_thr;//, uint8(4), ...
    char         sCUCFillTh         [32] = "cuc_fill_thr"; //UINT8     cuc_fill_thr;//', uint8(9), ...
    char         sCUCRemoveTh       [32] = "cuc_rm_thr"; //UINT8     cuc_rm_thr;//', uint8(4),         
	char         sCUCVecRepEn       [32] = "cuc_vec_rep_en"; //bool;
	char         sCUCPrePh1Vec      [32] = "cuc_pre_ph1_vec"; //
	char         sCUCPreUncovMask   [32] = "cuc_pre_uncov_mask"; //
	char         sCUCExtEn          [32] = "cuc_ext_en"; //bool
	char         sCUCNoUcOverrepEn  [32] = "cuc_no_uc_overrep_en";//bool;
	char         sCUCNoUcOverrepThr [32] = "cuc_no_uc_overrep_thr";//UINT16    ;
	char         sCUCUcHitCntThr    [32] = "cuc_uc_hit_cnt_thr"; //UINT8;
    char         sCUCSadDiffEn      [32] = "cuc_sad_diff_en";//bool
    char         sCUCSadDiffThr     [32] = "cuc_sad_diff_thr"; //UINT16
	//UINT8     cuc_delta_thr;
	//UINT8     cuc_dlt_diff_thr;
	//bool      cuc_vec_rep_en;
	//INT16*    cuc_pre_ph0_vec;
	//UINT8*    cuc_pre_uncov_mask;

	mxArray *    pmxaTemp;
	UINT8*       pui8Temp;
	UINT16*      pui16Temp;
	INT16*       pi16Temp;
	UINT32*      pui32Temp;

	mexPrintf("parser vp-filter parameters\n");
	//INT16*    cur_vector;
	pmxaTemp = mxGetField(pmxaParam, 0, sCurVector);
	pi16Temp = (INT16*)  mxGetData(pmxaTemp);
	pParam->cur_vector  = pi16Temp;
	mexPrintf("cur_vector: @%H\n", pParam->cur_vector);

	//UINT32*   cur_sad;
	pmxaTemp = mxGetField(pmxaParam, 0, sCurSAD);
	pui32Temp = (UINT32*)  mxGetData(pmxaTemp);
	pParam->cur_sad  = pui32Temp;
	mexPrintf("cur_sad: @%H\n", pParam->cur_sad);

	//UINT8*    cur_apl;
	pmxaTemp = mxGetField(pmxaParam, 0, sCurAPL);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cur_apl  = pui8Temp;
	mexPrintf("cur_apl: @%H\n", pParam->cur_apl);

	//UINT16*   cur_dtl;
	pmxaTemp = mxGetField(pmxaParam, 0, sCurDtl);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->cur_dtl  = pui16Temp;
	mexPrintf("cur_dtl: @%H\n", pParam->cur_dtl);

	//INT16*    pre_vector;
	pmxaTemp = mxGetField(pmxaParam, 0, sPreVector);
	pi16Temp = (INT16*)  mxGetData(pmxaTemp);
	pParam->pre_vector  = pi16Temp;
	mexPrintf("pre_vector: @%H\n", pParam->pre_vector);
	//UINT32*   pre_sad;
	pmxaTemp = mxGetField(pmxaParam, 0, sPreSAD);
	pui32Temp = (UINT32*)  mxGetData(pmxaTemp);
	pParam->pre_sad  = pui32Temp;
	mexPrintf("pre_sad: @%H\n", pParam->pre_sad);
	//UINT8*    pre_apl;
	pmxaTemp = mxGetField(pmxaParam, 0, sPreAPL);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->pre_apl  = pui8Temp;
	mexPrintf("pre_apl: @%H\n", pParam->pre_apl);
	//UINT16*   pre_dtl;
	pmxaTemp = mxGetField(pmxaParam, 0, sPreDtl);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->pre_dtl  = pui16Temp;
	mexPrintf("pre_dtl: @%H\n", pParam->pre_dtl);

	//UINT16    block_number[2];
	pmxaTemp = mxGetField(pmxaParam, 0, sBlkNum);
	pui16Temp = (UINT16*)mxGetData(pmxaTemp);
	pParam->block_number[0]  =  pui16Temp[0];
	pParam->block_number[1]  =  pui16Temp[1];
	mexPrintf("block_number %d,%d\n", pParam->block_number[0], pParam->block_number[1]);
	//UINT8*    block_size[2];
	pmxaTemp = mxGetField(pmxaParam, 0, sBlkSz);
	pui8Temp = (UINT8*)mxGetData(pmxaTemp);
	pParam->block_size[0]  =  pui8Temp[0];
	pParam->block_size[1]  =  pui8Temp[1];
	mexPrintf("block_size %d,%d\n", pParam->block_size[0], pParam->block_size[1]);
	//UINT8     temp_phase;
	pmxaTemp = mxGetField(pmxaParam, 0, sTempPhase);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->temp_phase  = pui8Temp[0];
	mexPrintf("temp_phase : %d\n  ", pParam->temp_phase);
	//UINT8     vec_precision;
	pmxaTemp = mxGetField(pmxaParam, 0, sVecPrecision);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->vec_precision[0]  = 1<<pui8Temp[0];
	pParam->vec_precision[1]  = 1<<pui8Temp[1];
	mexPrintf("vec_precision : %d, %d\n  ", pParam->vec_precision[0], pParam->vec_precision[1]);

	//UINT8     vp_order;   //ss/ts/med/aav order
	pmxaTemp = mxGetField(pmxaParam, 0, sVpOrder);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->vp_order  = pui8Temp[0];
	mexPrintf("vp_order : %d\n  ", pParam->vp_order);

	//bool      ss_en;      //spatial smooth: 1d tap7 lpf, 1 1 1 2 1 1 1
	pmxaTemp = mxGetField(pmxaParam, 0, sSSEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->ss_en  = (pui8Temp[0]!=0);
	mexPrintf("ss_en : %d\n  ", pParam->ss_en);
	
	//char         sSSThr             [32] = "ss_thr";
	pmxaTemp = mxGetField(pmxaParam, 0, sSSThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->ss_thr  = pui16Temp[0];
	mexPrintf("ss_thr : %d\n  ", pParam->ss_thr);


	//bool      ts_en;      //temporal smooth:
	pmxaTemp = mxGetField(pmxaParam, 0, sTSEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->ts_en  = (pui8Temp[0]!=0);
	mexPrintf("ts_en : %d\n  ", pParam->ts_en);

	//char         sTSThr             [32] = "ts_thr";
	pmxaTemp = mxGetField(pmxaParam, 0, sTSThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->ts_thr  = pui16Temp[0];
	mexPrintf("ts_thr : %d\n  ", pParam->ts_thr);

	//bool      med_en;    //median
	pmxaTemp = mxGetField(pmxaParam, 0, sMedEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->med_en = (pui8Temp[0]!=0);
	mexPrintf("med_en : %d\n  ", pParam->med_en);
	//bool      med_mode;  //0:original 1:apl adaptive median
	pmxaTemp = mxGetField(pmxaParam, 0, sMedMode);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->med_mode = (pui8Temp[0]!=0);
	mexPrintf("med_mode : %d\n  ", pParam->med_mode);
	//UINT8     med_aam_apl_diff; //min/max diff in window
	pmxaTemp = mxGetField(pmxaParam, 0, sMedAAMAplDiff);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->med_aam_apl_diff = pui8Temp[0];
	mexPrintf("med_aam_apl_diff : %d\n  ", pParam->med_aam_apl_diff);

	//bool      aav_en;    //APL adjust vector:
	pmxaTemp = mxGetField(pmxaParam, 0, sAAVEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->aav_en = (pui8Temp[0]!=0);
	mexPrintf("aav_en : %d\n  ", pParam->aav_en);
	//UINT8     aav_range;
	pmxaTemp = mxGetField(pmxaParam, 0, sAAVRange);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->aav_range = pui8Temp[0];
	mexPrintf("aav_range : %d\n  ", pParam->aav_range);
    //UINT8     aav_apl_diff_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sAAVAplDiffThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->aav_apl_diff_thr = pui8Temp[0];
	mexPrintf("aav_apl_diff_thr : %d\n  ", pParam->aav_apl_diff_thr);
	//UINT8 aav_apl_consist_thr
	pmxaTemp = mxGetField(pmxaParam, 0, sAAVAplConsisThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->aav_apl_consist_thr = pui8Temp[0];
	mexPrintf("aav_apl_consist_thr : %d\n  ", pParam->aav_apl_consist_thr);		
	//UINT16    aav_vec_diff_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sAAVVecDiffThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->aav_vec_diff_thr = pui16Temp[0];
	mexPrintf("aav_vec_diff_thr : %d\n  ", pParam->aav_vec_diff_thr);

	//UINT8     cuc_delta_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCDltThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_delta_thr = pui8Temp[0];
	//UINT8     cuc_dlt_diff_thr;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCDltDiffThr);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_dlt_diff_thr = pui8Temp[0];
	//bool      cuc_fill_en;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCFillEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_fill_en = (pui8Temp[0]!=0);
	mexPrintf("cuc_fill_en : %d\n  ", pParam->cuc_fill_en);
	//bool cuc_ext_en 
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCExtEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_ext_en = (pui8Temp[0]!=0);
	mexPrintf("cuc_ext_en : %d\n  ", pParam->cuc_ext_en);

	//UINT8 cuc_fill_lr_thr
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCFillLRTh);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_fill_lr_thr = pui8Temp[0];
	//UINT8 cuc_fill_thr
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCFillTh);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_fill_thr = pui8Temp[0];
	//UINT8 cuc_rm_thr
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCRemoveTh);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_rm_thr = pui8Temp[0];
	//bool      cuc_vec_rep_en;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCVecRepEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_vec_rep_en = (pui8Temp[0]!=0);
	mexPrintf("cuc_vec_rep_en : %d\n  ", pParam->cuc_vec_rep_en);
	//INT16*    cuc_pre_ph0_vec;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCPrePh1Vec);
	pi16Temp = (INT16*)  mxGetData(pmxaTemp);
	pParam->cuc_pre_ph1_vec  = pi16Temp;
	mexPrintf("cuc_pre_ph1_vec: @%H\n", pParam->cuc_pre_ph1_vec);
	//UINT8*    cuc_pre_uncov_mask;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCPreUncovMask);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_pre_uncov_mask  = pui8Temp;
	mexPrintf("cuc_pre_uncov_mask: @%H\n", pParam->cuc_pre_uncov_mask);

	//char         sCUCNoUcOverrepEn  [32] = "cuc_no_uc_overrep_en";//bool;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCNoUcOverrepEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_no_uc_overrep_en = (pui8Temp[0]!=0);
	mexPrintf("cuc_no_uc_overrep_en : %d\n  ", pParam->cuc_no_uc_overrep_en);
	
	//char         sCUCNoUcOverrepThr [32] = "cuc_no_uc_overrep_thr";//UINT16    ;
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCNoUcOverrepThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->cuc_no_uc_overrep_thr = pui16Temp[0];
	mexPrintf("cuc_no_uc_overrep_thr : %d\n  ", pParam->cuc_no_uc_overrep_thr);

   // char 		sCUCUcHitCntThr    [32] = "cuc_uc_hit_cnt_thr"; //UINT8;
    pmxaTemp = mxGetField(pmxaParam, 0, sCUCUcHitCntThr);
	pui16Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_uc_hit_cnt_thr= pui16Temp[0];
	mexPrintf("cuc_uc_hit_cnt_thr : %d\n	", pParam->cuc_uc_hit_cnt_thr);

    //	    char         sCUCSadDiffEn      [32] = "cuc_sad_diff_en";//bool
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCSadDiffEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pParam->cuc_sad_diff_en= (pui8Temp[0]!=0);
	mexPrintf("cuc_sad_diff_en : %d\n  ", pParam->cuc_sad_diff_en);

	
    //char         sCUCSadDiffThr     [32] = "cuc_sad_diff_thr"; //UINT16
	pmxaTemp = mxGetField(pmxaParam, 0, sCUCSadDiffThr);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pParam->cuc_sad_diff_thr= pui16Temp[0];
	mexPrintf("cuc_sad_diff_thr : %d\n  ", pParam->cuc_sad_diff_thr);

	return true;

 }


mxArray *  call_vp(const mxArray* pmxaPh0Param, const mxArray* pmxaPh1Param, const mxArray* pmxaLRParam, const mxArray* pmxaLogoParam)
{

    T_VP_PARAM   tPh0Param, tPh1Param, tLRParam;
	T_COMMON_VP_PARAM tLogoParam;

	mxArray*     pResult;
	char**       psFldNames;
	const int    nFldNum     = 15;
	char         sMCVec    [32] = "mc_vector";
	char         sPh0Vec   [32] = "ph0_vector";
	char         sPh0CUCVec[32] = "ph0_cuc_vector";
	char         sPh1Vec   [32] = "ph1_vector";
	char         sPh1CUCVec[32] = "ph1_cuc_vector";
	char         sLRVec    [32] = "lr_vector";
	char         sLogoMask [32] = "logo_mask";
	char         sCovMask  [32] = "cover_mask";
	char         sUncovMask[32] = "uncover_mask";
	char         sCUCMask  [32] = "cuc_mask";
	char         sObjMask  [32] = "obj_mask";
	char         sStHistory[32] = "static_history";
	char         sConMotCnt[32] = "cont_motion_count";
	char         sMotMask  [32] = "motion_area";
	char         sDtlMask  [32] = "detail_area";
	unsigned int iOutDims[2], iLROutDims[2];
	unsigned int iVecDims[3], iLRVecDims[3];
	mxArray      *pmxaMCVec, *pmxaPh0Vec, *pmxaPh1Vec, *pmxaLRVec;
	mxArray      *pmxaPh0CUCVec, *pmxaPh1CUCVec;
	mxArray      *pmxaCovMask, *pmxaUncovMask, *pmxaCUCMask, *pmxaObjMask;
	mxArray      *pmxaLogoMask, *pmxaLogoHistory,*pmxaConMotCnt, *pmxaMotionArea, *pmxaDetailArea;
	INT16        *pMCVec, *pPh0Vec, *pPh1Vec, *pLRVec;
	INT16        *pPh0CUCVec, *pPh1CUCVec;
	UINT8        *pObjMask;
	UINT8        *pLogoMask, *pLogoHistory, *pConMotCnt, *pMotionArea, *pDetailArea;
	UINT8        *pCovMask, *pUncovMask;
	INT8         *pCUCMask;


    parser_vp_parameters(pmxaPh0Param, &tPh0Param);
    parser_vp_parameters(pmxaPh1Param, &tPh1Param);
    parser_vp_parameters(pmxaLRParam,  &tLRParam);
	parser_logo_parameters(pmxaLogoParam, &tLogoParam);


	//create output structure
	psFldNames = mxCalloc(nFldNum, sizeof(char*));
	psFldNames[0]  = sMCVec;
	psFldNames[1]  = sPh0Vec;
	psFldNames[2]  = sPh1Vec;
	psFldNames[3]  = sLRVec;
	psFldNames[4]  = sLogoMask;
	psFldNames[5]  = sCovMask;
	psFldNames[6]  = sUncovMask;
	psFldNames[7]  = sCUCMask;
	psFldNames[8]  = sObjMask;
	psFldNames[9]  = sStHistory;
	psFldNames[10] = sConMotCnt;
	psFldNames[11] = sMotMask;
	psFldNames[12] = sDtlMask;
	psFldNames[13] = sPh0CUCVec;
	psFldNames[14] = sPh1CUCVec;

	//get output dim
	iOutDims[0]   = tPh0Param.block_number[0];
	iOutDims[1]   = tPh0Param.block_number[1];
	iLROutDims[0] = tLRParam.block_number[0];
	iLROutDims[1] = tLRParam.block_number[1];
	iVecDims[2]   =  2;
	iVecDims[0]   =  iOutDims[0];
	iVecDims[1]   =  iOutDims[1];
	iLRVecDims[2] =  2;
	iLRVecDims[0] =  iLROutDims[0];
	iLRVecDims[1] =  iLROutDims[1];



	pResult    = mxCreateStructMatrix(1, 1, nFldNum, (const char **)psFldNames);
	mexPrintf("create struct success\n");
	mxFree(psFldNames);
	//vectors
	mexPrintf("VectorDims: %d, %d\n", iVecDims[0], iVecDims[1]);
	//MCVec
	pmxaMCVec  =  mxCreateNumericArray(3, (const mwSize *)&iVecDims, mxINT16_CLASS, mxREAL);
	pMCVec     =  (INT16*)mxGetData(pmxaMCVec);
    //ph0vec
	pmxaPh0Vec =  mxCreateNumericArray(3, (const mwSize *)&iVecDims, mxINT16_CLASS, mxREAL);
	pPh0Vec    =  (INT16*)mxGetData(pmxaPh0Vec);
    //ph1vec
	pmxaPh1Vec =  mxCreateNumericArray(3, (const mwSize *)&iVecDims, mxINT16_CLASS, mxREAL);
	pPh1Vec    =  (INT16*)mxGetData(pmxaPh1Vec);
    //lrvec
	pmxaLRVec  =  mxCreateNumericArray(3, (const mwSize *)&iLRVecDims, mxINT16_CLASS, mxREAL);
	pLRVec     =  (INT16*)mxGetData(pmxaLRVec);
	//logo mask
	pmxaLogoMask   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pLogoMask      =  (UINT8*)mxGetData(pmxaLogoMask);
	//Cov mask
	pmxaCovMask   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pCovMask      =  (UINT8*)mxGetData(pmxaCovMask);
	//Uncov mask
	pmxaUncovMask =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pUncovMask      =  (UINT8*)mxGetData(pmxaUncovMask);
	//CUC mask
	pmxaCUCMask =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxINT8_CLASS, mxREAL);
	pCUCMask      =  (INT8*)mxGetData(pmxaCUCMask);
	//obj mask
	pmxaObjMask   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pObjMask  =  (UINT8*)mxGetData(pmxaObjMask);
	//static history
	pmxaLogoHistory   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pLogoHistory  =  (UINT8*)mxGetData(pmxaLogoHistory);
	//char         sConMotCnt[32] = "cont_motion_count";
	pmxaConMotCnt   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pConMotCnt    =  (UINT8*)mxGetData(pmxaConMotCnt);
	//motion area
	pmxaMotionArea   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pMotionArea  =  (UINT8*)mxGetData(pmxaMotionArea);
	//detail_area
	pmxaDetailArea   =  mxCreateNumericArray(2, (const mwSize *)&iOutDims, mxUINT8_CLASS, mxREAL);
	pDetailArea  =  (UINT8*)mxGetData(pmxaDetailArea);
    //ph0CUCvec
	pmxaPh0CUCVec =  mxCreateNumericArray(3, (const mwSize *)&iVecDims, mxINT16_CLASS, mxREAL);
	pPh0CUCVec    =  (INT16*)mxGetData(pmxaPh0CUCVec);
    //ph1CUCvec
	pmxaPh1CUCVec =  mxCreateNumericArray(3, (const mwSize *)&iVecDims, mxINT16_CLASS, mxREAL);
	pPh1CUCVec    =  (INT16*)mxGetData(pmxaPh1CUCVec);

	vp(&tPh0Param, &tPh1Param, &tLRParam, &tLogoParam, pMCVec, pPh0Vec, pPh0CUCVec, pPh1Vec, pPh1CUCVec, pLRVec, pLogoMask, pCovMask, pUncovMask, pCUCMask, pObjMask, pLogoHistory, pConMotCnt, pMotionArea, pDetailArea);

	mxSetFieldByNumber(pResult, 0, 0,  pmxaMCVec);
	mxSetFieldByNumber(pResult, 0, 1,  pmxaPh0Vec);
	mxSetFieldByNumber(pResult, 0, 2,  pmxaPh1Vec);
	mxSetFieldByNumber(pResult, 0, 3,  pmxaLRVec);
	mxSetFieldByNumber(pResult, 0, 4,  pmxaLogoMask);
	mxSetFieldByNumber(pResult, 0, 5,  pmxaCovMask);
	mxSetFieldByNumber(pResult, 0, 6,  pmxaUncovMask);
	mxSetFieldByNumber(pResult, 0, 7,  pmxaCUCMask);
	mxSetFieldByNumber(pResult, 0, 8,  pmxaObjMask);
	mxSetFieldByNumber(pResult, 0, 9,  pmxaLogoHistory);
	mxSetFieldByNumber(pResult, 0, 10, pmxaConMotCnt);
	mxSetFieldByNumber(pResult, 0, 11, pmxaMotionArea);
	mxSetFieldByNumber(pResult, 0, 12, pmxaDetailArea);
	mxSetFieldByNumber(pResult, 0, 13, pmxaPh0CUCVec);
	mxSetFieldByNumber(pResult, 0, 14, pmxaPh1CUCVec);

	return pResult;

}

/* mex file interface */
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray* prhs[] )
{


    if (nrhs != 4) 
        mexErrMsgTxt("vp need 4 input parameters."); 
    else if (nlhs != 1)
        mexErrMsgTxt("vp need 1 output arguments."); 
	
    /*check and get common parameters*/
    VP_RESULT = call_vp(VP_PH0_PARAM, VP_PH1_PARAM, VP_LR_PARAM, VP_LOGO_PARAM);

    return;
}

